package mop.controller;

import java.sql.Timestamp;
import java.util.List;

import mop.domain.task.TaskPool;
import mop.exception.IllegalDeadlineException;
import mop.exception.IllegalDependencyException;
import mop.exception.IllegalDescriptionException;
import mop.exception.IllegalDuplicationException;
import mop.exception.IllegalStatusException;
import mop.exception.IllegalTerminationException;

/**
 * The connection between GUI and domain.
 * Only knows built-in Java data types and strings.
 * 
 * @invar	Has no variables of its own, except for pool,
 * 			which is a reference to a static variable.
 *        
 * @author	MOP Team 7
 */
public class TaskController {
	
	private static TaskController instance;
	
	/**
	 * Create a TaskController with no extra settings.
	 * Constructor must be at protected level.
	 * Allows inheritance, but no out of package creation.
	 * 
	 * @post	TaskController instance created
	 */
	protected TaskController(){}
	
	/***************************************************************************
	 * 							instance
	 ***************************************************************************/
	
	/**
	 * Always use this function to access TaskController.
	 * 
	 * @effect 	Task controller gets created - if it didn't exist yet.
	 *  		|instance = new TaskController()
	 * 
	 * @return 	The static instance of TaskController.
	 */
	public static TaskController getInstance()
	{
		if(instance == null)
		{
			instance = new TaskController();
		}
		return instance;
	}
	
	/***************************************************************************
	 * 							Task creation
	 ***************************************************************************/
	
	/**
	 * Creates Task with given values.
	 * 
	 * @param 	description
	 *  		The description of the task.
	 * @param 	start
	 *  		start date of the task.
	 * @param 	deadline
	 *  		deadline of the task.
	 * @param 	duration
	 *  		Expected duration of the task.
	 * @param 	res
	 *  		List of resource names for this task.
	 * @param 	dep
	 *  		List of dependent task (names) of this task.
	 *  
	 * @throws 	IllegalDuplicateException
	 * 			if the task is a duplicate
	 * 			|!TaskPool.isUniqueresource(name)
	 *       
	 * @throws 	IllegalDescriptionException
	 * 			if the deadline is not a valid deadline according to business rule 1
	 * 			|!Task.isValidDescription(deadline,start,duration,dep)
	 */
	public void createTask(String description, Timestamp start, Timestamp deadline, Timestamp duration, List<String> res, List<String> dep) 
		throws IllegalDeadlineException, IllegalDescriptionException, IllegalDuplicationException
	{
		TaskPool.getInstance().createTask(description, start, deadline, duration, res, dep);
	}
	
	/***************************************************************************
	 * 							Task removal
	 ***************************************************************************/
	
	/**
	 * Tries to remove a task corresponding with the given description.
	 * 
	 * @param 	taskDescription
	 * 			Description of the task to be removed
	 * 
	 * @throws 	IllegalTerminationException 
	 * 
	 * @effect 	Tries to remove a task.
	 *  		|TaskPool.getInstance().tryRemoveTask(taskDescription);
	 *  
	 * @return	List with parent names of task, if task has parents. Null otherwise.
	 */
	public List<String> tryRemoveTask(String taskDescription) 
		throws IllegalTerminationException
	{
		return TaskPool.getInstance().tryRemoveTask(taskDescription);
	}
	
	/**
	 * Removes task and all parents, if required, for given task name.
	 * 
	 * @param 	taskDescription
	 * 			Description of task to be removed
	 * 
	 * @param 	parents
	 *  		Whether to terminate and remove task parents.
	 * 
	 * @throws 	IllegalTerminationException 
	 * 
	 * @effect 	Remove task according to settings.
	 *  		|TaskPool.getInstance().forceRemoveTask(taskDescription, parents);
	 */
	public void forceRemoveTask(String taskDescription, boolean parents) 
		throws IllegalTerminationException
	{
		TaskPool.getInstance().forceRemoveTask(taskDescription, parents);
	}
	
	/***************************************************************************
	 * 							Get task details
	 ***************************************************************************/
	
	/**
	 * Returns the status of the task with given name.
	 * Doesn't differentiate between available and unavailable.
	 * 
	 * @param 	taskDescription
	 * 			Description of the task.
	 * 
	 * @return 	The status.
	 */
	public String getStatus(String taskDescription)
	{
		return TaskPool.getInstance().getStatus(taskDescription);
	}
	
	/**
	 * Returns the extended status.
	 * The extended status differentiates between available and unavailable, when the task is not yet finished.
	 *
	 * @param 	taskDescription
	 * 			Description of the task.
	 * 
	 * @return	Status available, if task is available.
	 * 			Status unavailable, if task is unavailable due to an unfinished dependency 
	 * 				or due to an unavailable resource.
	 * 			Normal status, if task is finished.
	 *  		|getStatus()
	 */
	public String getExtendedStatus(String taskDescription)
	{
		return TaskPool.getInstance().getExtendedStatus(taskDescription);
	}
	
	/**
	 * Returns list with start date, duration and deadline of task with given taskDescription.
	 * 
	 * @param 	taskDescription
	 * 			Description of the task.
	 * 
	 * @return 	List with timestamps of date, duration and deadline
	 */
	public List<Timestamp> getDetails(String taskDescription)
	{
		return TaskPool.getInstance().getSchedule(taskDescription);
	}
	
	/**
	 * Returns list with dependencies of the task with given taskDescription.
	 * 
	 * @param 	taskDescription
	 * 			Description of the task.
	 * 
	 * @return 	List with dependencies of the task with given taskDescription.
	 */
	public List<String> getDependencies(String taskDescription)
	{
		return TaskPool.getInstance().getDependencies(taskDescription);
	}
	
	/**
	 * Returns list with resources required by the task with given taskDescription.
	 * 
	 * @param 	taskDescription
	 * 			Description of the task.
	 * 
	 * @return 	List with resources required by the task with given taskDescription.
	 */
	public List<String> getResources(String taskDescription)
	{
		return TaskPool.getInstance().getResources(taskDescription);
	}
	
	
	/***************************************************************************
	 * 							Update task
	 ***************************************************************************/
	
	/**
	 * Updates a task status.
	 * 
	 * @param 	taskDescription
	 * 			Description of the task.
	 * @param 	status
	 * 			The new task status.
	 * 
	 * @throws 	IllegalStatusException 
	 */
	public void updateStatus(String taskDescription, String status) 
		throws IllegalStatusException
	{
		TaskPool.getInstance().updateStatus(taskDescription, status);
	}

	
	/**
	 * Updates task details.
	 * 
	 * @param 	oldDescription
	 * 			The old description of a task.
	 * @param 	newDescription
	 *  		The new description for the task.
	 * @param 	start
	 * 			start date of task.
	 * @param 	deadline
	 * 			deadline date of task.
	 * @param 	duration
	 * 			duration date of task.
	 * @param 	res
	 * 			List of resource descriptions task uses.
	 * @param 	dep
	 * 			List of task description the task depends on.
	 *       
	 * @throws 	IllegalDeadlineException
	 * 			if the deadline is not a valid deadline, according to business rule 1
	 * 			|!Task.isValidDeadline(deadline,start,duration,dep)
	 * 
	 * @throws 	IllegalDuplicateException
	 * 			if the task is a duplicate
	 * 			|!TaskPool.isUniqueresource(name)
	 *       
	 * @throws 	IllegalDescriptionException
	 * 			if the deadline is not a valid deadline according to business rule 1
	 * 			|!Task.isValidDescription(deadline,start,duration,dep)
	 * 
	 * @throws 	IllegalDependencyException
	 * 			if the given dependencies create a loop in the dependency graph
	 * 			|!Task.isValidDependencies(findTask(oldDescription),dep)
	 */
	
	public void updateDetails(String oldDescription, String newDescription, Timestamp start, 
			Timestamp deadline, Timestamp duration, List<String> res, List<String> dep) 
		throws IllegalDeadlineException, IllegalDuplicationException, IllegalDependencyException, IllegalDescriptionException
	{
		TaskPool.getInstance().updateDetails(oldDescription, newDescription, start, deadline, duration, res, dep);
	}
	
	/***************************************************************************
	 * 							Task Lists
	 ***************************************************************************/
	/**
	 * Returns list with descriptions of all tasks in pool.
	 * 
	 * @return 	List of strings representing descriptions of all tasks in pool.
	 */
	public List<String> getAllTasksList()
	{
		return TaskPool.getInstance().getAllTasksList();
	}
	
	/**
	 * Returns list with descriptions of all tasks in pool of current user.
	 * 
	 * @return List with descriptions of tasks of current user.
	 */
	public List<String> getUserTasksList()
	{
		return TaskPool.getInstance().getUserTasksList();
	}
	
	/**
	 * Returns list with focus tasks.
	 * 
	 * @return	List with tasks of current user that end today, sorted by deadline.
	 * 			If no tasks must be finished today, it show the top 10 tasks with earliest deadlines.
	 */
	public List<String> getFocusTasksList()
	{
		return TaskPool.getInstance().getFocusTasksList();
	}

}